package main

import (
	"CCServer.com/练习/gomodule"
	"CCServer.com/练习/gluamapper"
	"fmt"
	"github.com/yuin/gopher-lua"
	"os"
	"os/signal"
	"reflect"
	"syscall"
)

func main() {
	L := lua.NewState()
	defer L.Close()

	mapTest()
	funTest()
	structTest()

	go func() {
		L.PreloadModule("gomodule", gomodule.Loader)
		if err := L.DoFile("main.lua"); err != nil {
			panic(err)
		}
	}()

	chSig := make(chan os.Signal)
	signal.Notify(chSig, syscall.SIGINT, syscall.SIGTERM)
	fmt.Println("Signal:%v", <-chSig)
	fmt.Println("___________end")
	//for {
	//	//
	//	//if err := L.DoFile("test.lua"); err != nil {
	//	//	panic(err)
	//	//}
	//
	//	time.Sleep(time.Second * 10)
	//}

//	if err := L.DoString(`local m = require("mymodule")
//m.myfunc()
//print(m.name)
//
//`); err != nil {
//		panic(err)
//	}




}



type testRole struct {
	Name string
}

type testPerson struct {
	Name      string
	Age       int
	WorkPlace string
	Role      []*testRole
}

type testStruct struct {
	Nil    interface{}
	Bool   bool
	String string
	Number int `gluamapper:"number_value"`
	Func   interface{}
}

func mapTest() {
	L := lua.NewState()
	defer L.Close()
	if err := L.DoString(`
    person = {
      name = "Michel",
      age  = "31", -- weakly input
      work_place = "San Jose",
      role = {
        {
          name = "Administrator"
        },
        {
          name = "Operator"
        }
      }
    }
	`); err != nil {
		//t.Error(err)
	}
	var person testPerson
	if err := gluamapper.Map(L.GetGlobal("person").(*lua.LTable), &person); err != nil {
		//t.Error(err)
		fmt.Println(err)
	}
	//errorIfNotEqual(t, "Michel", person.Name)
	//errorIfNotEqual(t, 31, person.Age)
	//errorIfNotEqual(t, "San Jose", person.WorkPlace)
	//errorIfNotEqual(t, 2, len(person.Role))
	fmt.Println( "Administrator", person.Role[0].Name)
	//errorIfNotEqual(t, "Operator", person.Role[1].Name)

	fmt.Printf("___person:%+v", person)


}



func funTest() {
	L := lua.NewState()
	defer L.Close()
	if err := L.DoString(`
    tbl = {
      ["Nil"] = nil,
      ["Bool"] = true,
      ["String"] = "string",
      ["Number_value"] = 10,
      ["Func"] = function() print("2222222hello") end
    }
	`); err != nil {

	}
	var stct testStruct

	if err := gluamapper.NewMapper(gluamapper.Option{NameFunc: gluamapper.Id}).Map(L.GetGlobal("tbl").(*lua.LTable), &stct); err != nil {
		fmt.Println(err)
	}
	fmt.Println("")
	L.CallByParam(lua.P{
		Fn:stct.Func.(*lua.LFunction),
	}, lua.LNumber(10))

}

func structTest(){
	type TestPerson struct {
		Name      lua.LString
		Age       int
		WorkPlace string
		Role2     testRole
		Role      []*testRole
	}
	L := lua.NewState()
	defer L.Close()




	st := TestPerson{
		"xxx",
		18,
		"place",
		testRole{
			 "role2",
		},
		[]*testRole{
			{"role1"},
			{"role2"},
		},
	}
	person := structToTable(L, st)
	L.SetGlobal("person2", person)

	if err := L.DoString(`
    	print("_222_person_", person2)
		for k, v in pairs(person2) do 
			print("person->", k, v)
			if type(v) == "table" then 
				print("___table__", #v)
				for kk, vv in pairs(v) do 
					print(" 2person->", kk, vv)
				end
			end
		end
	`); err != nil {
		fmt.Println("__err", err)
	}
}


func structToTable(L *lua.LState, st interface{}) *lua.LTable{
	v := reflect.ValueOf(st)
	count := v.NumField()
	tb := L.NewTable()
	for i := 0; i < count; i++ {
		f := v.Field(i)
		//tagVal := v.Type().Field(i).Tag.Get("protobuf")
		//fmt.Println("__", tagVal, f.Type().Kind())
		key := v.Type().Field(i).Name
		val := f
		if f.Type().Kind().String() == "ptr" {
			val = f.Elem()
		} else {
		}
		fmt.Println(key, val)
		fmt.Println("__type_",val.Type().String(), val.Type().Kind())
		vtype := val.Type().String()
		kind := val.Type().Kind().String()

		if kind == "string" {
			tb.RawSet(lua.LString(key), lua.LString(val.String()))
		} else if kind == "int" || kind == "int32" || kind == "int64" {
			tb.RawSet(lua.LString(key), lua.LNumber(val.Int()))
		} else if kind == "float" {
			tb.RawSet(lua.LString(key), lua.LNumber(val.Float()))
		}else if kind == "bool" {
			tb.RawSet(lua.LString(key), lua.LBool(val.Bool()))
		}else if kind == "struct" {
			if vtype == "reflect.rtype" {
				return tb
			}
			t := structToTable(L, val)
			tb.RawSet(lua.LString(key), t)
		}
	}
	return tb
}